// Copyright (c) 2022 CHANGLEI. All rights reserved.

import 'dart:math';

import 'package:aircraft_war/bloc/game_state_cubit.dart';
import 'package:aircraft_war/commons/constants.dart';
import 'package:aircraft_war/components/aircraft.dart';
import 'package:aircraft_war/components/bullet.dart';
import 'package:aircraft_war/components/bullet_supply.dart';
import 'package:aircraft_war/components/enemy_aircraft.dart';
import 'package:aircraft_war/components/firepower_supply.dart';
import 'package:aircraft_war/foundation/sounds.dart';
import 'package:aircraft_war/foundation/timers.dart';
import 'package:flame/components.dart';

const _padding = 10.0;

/// Created by changlei on 2022/5/18.
///
/// 游戏操作台
class GameConsole extends GameStatePositionComponent {
  late final _aircraft = Aircraft();
  late final _timers = Timers(
    bulletBuilder: _buildBullet,
    enemyBuilder: _buildEnemy,
    supplyBuilder: _buildSupply,
  );

  bool _started = false;

  @override
  void onGameResize(Vector2 size) {
    super.onGameResize(size);
    this.size = size;
    onNewState(gameRef.stateCubit.state);
  }

  @override
  Future<void> onLoad() async {
    _aircraft.anchor = Anchor.topCenter;
    onNewState(gameRef.stateCubit.state);
    _resetAircraft();
  }

  @override
  void onNewState(GameState state) {
    if (state != GameState.stopped) {
      _resetAircraft();
    }
    switch (state) {
      case GameState.idle:
      case GameState.pending:
      case GameState.stopped:
        _started = false;
        _timers.stop();
        _timers.reset();
        _resetPendingPosition();
        break;
      case GameState.pausing:
        _timers.pause();
        _resetRunningPosition();
        break;
      case GameState.running:
        _timers.start();
        _resetRunningPosition();
        break;
    }
  }

  @override
  void update(double dt) {
    _timers.update(dt);
  }

  void _resetAircraft() {
    if (_aircraft.parent == null) {
      _aircraft.reset();
      add(_aircraft);
    }
  }

  void _resetPendingPosition() {
    _aircraft.position = Vector2(size.x / 2, size.y * 0.3);
  }

  void _resetRunningPosition() {
    if (_started) {
      return;
    }
    _started = true;
    _aircraft.position = Vector2(size.x / 2, size.y * 0.8);
  }

  void _buildBullet() {
    if (!gameRef.isRunning) {
      return;
    }
    final anchor = _aircraft.position - Vector2(bulletSize.x / 2, 0);
    final bulletCubit = gameRef.bulletCubit;

    if (bulletCubit.consume()) {
      _timers.speedDownBullet();
      Sounds.useBullet();
      add(Bullet(
        position: anchor,
        anchor: Anchor.bottomLeft,
      ));
    } else {
      _timers.speedUpBullet();
      Sounds.useBulletSupply();
      add(Bullet(
        type: BulletType.enhance,
        position: anchor.clone()..x = anchor.x - _aircraft.width / 3,
        anchor: Anchor.bottomLeft,
      ));
      add(Bullet(
        type: BulletType.enhance,
        position: anchor.clone()..x = anchor.x + _aircraft.width / 3,
        anchor: Anchor.bottomLeft,
      ));
    }
  }

  void _buildEnemy(EnemyType enemyType) {
    if (!gameRef.isRunning) {
      return;
    }
    final maxWidth = width - enemyType.size.x;
    final paddingRate = _padding / maxWidth;
    final offset = Random().nextDouble();
    add(
      EnemyAircraft(
        type: enemyType,
        position: Vector2(maxWidth * (offset + paddingRate) * (1 - paddingRate * 2), 0),
        anchor: Anchor.bottomLeft,
      )..growth(_timers.offset * 30),
    );
  }

  void _buildSupply() {
    if (!gameRef.isRunning) {
      return;
    }
    final firepowerCubit = gameRef.firepowerCubit;
    final bulletCubit = gameRef.bulletCubit;
    if (firepowerCubit.isMax && bulletCubit.isMax) {
      return;
    }
    final PositionComponent supply;
    if (Random().nextInt(100) % 5 == 0 && !firepowerCubit.isMax) {
      supply = FirepowerSupply();
    } else {
      supply = BulletSupply();
    }
    final maxWidth = width - supply.width;
    final paddingRate = _padding / maxWidth;
    final offset = Random().nextDouble();
    supply.position = Vector2(
      maxWidth * (offset + paddingRate) * (1 - paddingRate * 2) + supply.width / 2,
      -supply.height,
    );
    supply.anchor = Anchor.topCenter;
    add(supply);
  }
}
